/* $Header: duart.h,v 2.3 02/07/24 11:05:24 przybyls Exp $ */


/***********************************************************************/
/* INCLUDE FILE NAME: duart.h                                           */
/* ==================                                                  */
/*                                                                     */
/* Author:  Bob Cook                                                   */
/*                                                                     */
/* COMMENT:                                                            */
/*          Include file for files using the services of the DUART.    */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

#ifndef DUART_H
#define DUART_H

/*****************************/
/*   IFDEFS                  */
/*****************************/


/*****************************/
/*   SYMBOLIC CONSTANTS      */
/*****************************/
#define LAN_PORT        0    /* Internal serial port - port C of QUART */
#define HOST_PORT       1    /* Back serial port - port D of QUART */
#define INJECTOR1_PORT  2    /* Top Sampler serial port - port A of QUART */
#define INJECTOR2_PORT  3
#define TRAY_PORT       4

#define ENQ     0x05    /* ENQ (enquiry) character */
#define ACK     0x06    /* ACK (acknowledge) character */
#define DLE     0x10    /* DLE (datalink escape) character */
#define XON     0x11    /* XON (xmit on) character */
#define XOFF    0x13    /* XOFF (xmit off) character */
#define CAN     0x18    /* CAN (cancel) character */

#define XON_STATE   1   /* used with XonXoff_State variable */
#define XOFF_STATE  0

#define DUART_RX_BUF_SIZE 512  /* Size of duart buffer */
#define DUART_TX_BUF_SIZE 140 /* Size of duart buffer */
#define Rx_XOFF_POINT  200 /* buf count where XOFF is sent or RTS is set  */
#define Rx_XON_POINT   50  /* buf count where XON is sent or RTS is reset  */

/* Rs232SelfTest timeout */
#define RS232_TEST_TIMEOUT   2   /* gives at least 1 second time out */

#define DATA_LOSS   0xFFFF   /* used to indicate input buffer overflow */

/*****************************/
/*   MACROS                  */
/*****************************/

/*==========================================================================*
 * MACRO: GetBufPtr                                                         *
 *                                                                          *
 * PURPOSE: remove data from circular queue and update count                *
 *            Performs the same function as GetBuf except uses pointers     *
 *            to structure instead of the structure.                        *
 * WARNING: 1. Count variable is modified elsewhere.                        *
 *          2. Need interrupt protection if used in background              *
 *          3. Check for overflow before calling this macro.                *
 *==========================================================================*/

#define GetBufPtr(buf_v, item_addr)                                          \
/* void GetBufPtr(DUART_TX_BUF_TYPE buf_v, INT8 *item_addr) */               \
                                                                             \
{                                                                            \
   /* Check if ptr is at end of buffer. If it is, move to beginning. */      \
   if (buf_v->pfront == buf_v->pbufend)                                      \
      buf_v->pfront = buf_v->pbuffer;                                        \
   else                                                                      \
      buf_v->pfront++;                                                       \
                                                                             \
   *(item_addr) = *buf_v->pfront;                                            \
   buf_v->count--;                                                           \
}                                                                            \


/*==========================================================================*
 * MACRO: PutBufPtr                                                         *
 *                                                                          *
 * PURPOSE: put data into circular queue and update count                   *
 *            Performs the same function as PutBuf except uses pointers     *
 *            to structure instead of the structure.                        *
 * WARNING: 1. Count variable is modified elsewhere.                        *
 *          2. Need interrupt protection if used in background              *
 *          3. Check for overflow before calling this macro.                *
 *==========================================================================*/

#define PutBufPtr(pbuf_v, item)                                              \
/* void PutBufPtr(DUART_RX_BUF_TYPE *pbuf_v, INT16 item) */                  \
                                                                             \
{                                                                            \
   /* Check if ptr is at end of buffer. If it is, move to beginning. */      \
   if( pbuf_v->prear == pbuf_v->pbufend )                                    \
      pbuf_v->prear = pbuf_v->pbuffer;                                       \
   else                                                                      \
      pbuf_v->prear++;                                                       \
                                                                             \
   *pbuf_v->prear = (item);                                                  \
   pbuf_v->count++;                                                          \
}                                                                            \


/*==========================================================================*
 * MACRO: SetupDuartRdPacket                                                *
 *                                                                          *
 * PURPOSE: tries to get new read packet from the free queue and initialize *
 *           the packet.  If no packets are available it sets the           *
 *           Waiting_For_Rd_Packet flag.                                    *
 * WARNING:                                                                 *
 *==========================================================================*/
/* void SetUpDuartRdPacket(U_INT16 chan) */

#define SetUpDuartRdPacket(chan)                                            \
{                                                                           \
   GetPacket(Duart_CB[chan].pRd_Packet, Rd_Free_Q);                         \
   /* If more packets are available, set count and pointer. */              \
   if(Duart_CB[chan].pRd_Packet != NULL)                                    \
   {                                                                        \
      Duart_CB[chan].pRd_Packet->data_length = 0;                           \
      /* get 32 bit address */                                              \
      Duart_CB[chan].pRd_Data_Start = (BIT8 *)DMA_MEM +                     \
                                  Duart_CB[chan].pRd_Packet->data_start;    \
      /* set communication port */                                          \
      Duart_CB[chan].pRd_Packet->comm_port = chan;                          \
   }                                                                        \
   else                                                                     \
   {                                                                        \
      Duart_CB[chan].Waiting_For_Rd_Packet = TRUE;                          \
   }                                                                        \
}                                                                           \


/***************************************************************************/
/*                     CONTROL OF MODEM LINES                              */
/***************************************************************************/

/*
 *  DUART_IPR    ; Input Port Reg
 *  DUART_SOPR   ; Set Output Port Bits
 *  DUART_ROPR   ; Reset Output Port Bits
 *  NOTE:
 *          SPACE = ON = +15v = 0v or 0 at 26C92
 *          MARK = OFF = -15v = 5v or 1 at 26C92
 */


/*==========================================================================*
 * MACRO: Test_CTS_ON                                                       *
 *                                                                          *
 * PURPOSE: determines if CTS is ON or OFF for channel specified.           *
 *                                                                          *
 * RETURNS:    0    if CTS is OFF                                           *
 *          nonzero if CTS is ON                                            *
 *                                                                          *
 *==========================================================================*/

#define Test_CTS_ON(chan)                                                    \
                                                                             \
   (chan == DRTE_PORT ? (UART_MSR & U_CTS) :                                 \
                        ( (~*Duart_CB[chan].pIPR) & CTS ))                   \


/*==========================================================================*
 * MACRO: Test_DSR_ON                                                       *
 *                                                                          *
 * PURPOSE: determines if DSR is ON or OFF for channel specified.           *
 *                                                                          *
 * RETURNS:    0    if DSR is OFF                                           *
 *          nonzero if DSR is ON                                            *
 *                                                                          *
 *==========================================================================*/

#define Test_DSR_ON(chan)                                                    \
                                                                             \
   (chan == DRTE_PORT ? (UART_MSR & U_DSR) :                                 \
                        ( (~*Duart_CB[chan].pIPR) & DSR ))                   \

/*==========================================================================*
 * MACRO: Set_RTS_ON                                                        *
 *                                                                          *
 * PURPOSE: Sets RTS for channel specified to ON (SPACE).                   *
 *                                                                          *
 *==========================================================================*/

#define Set_RTS_ON(chan)                                                     \
                                                                             \
{                                                                            \
   if (chan == DRTE_PORT)                                                    \
   {                                                                         \
      Duart_CB[4].MCR_Copy |= U_RTS;                                         \
      UART_MCR =  Duart_CB[4].MCR_Copy;                                      \
   }                                                                         \
   else                                                                      \
   {                                                                         \
      *Duart_CB[chan].pOPR |= RTS;                                           \
   }                                                                         \
}                                                                            \

/*==========================================================================*
 * MACRO: Set_RTS_OFF                                                       *
 *                                                                          *
 * PURPOSE: Sets RTS for channel specified to OFF (MARK).                   *
 *                                                                          *
 *==========================================================================*/

#define Set_RTS_OFF(chan)                                                    \
                                                                             \
{                                                                            \
   if (chan == DRTE_PORT)                                                    \
   {                                                                         \
      Duart_CB[4].MCR_Copy &= ~U_RTS;                                        \
      UART_MCR =  Duart_CB[4].MCR_Copy;                                      \
   }                                                                         \
   else                                                                      \
   {                                                                         \
      *Duart_CB[chan].pOPR &= ~RTS;                                          \
   }                                                                         \
}                                                                            \

/*==========================================================================*
 * MACRO: Set_DTR_ON                                                        *
 *                                                                          *
 * PURPOSE: Sets DTR for channel specified to ON (SPACE).                   *
 *                                                                          *
 *==========================================================================*/

#define Set_DTR_ON(chan)                                                     \
                                                                             \
{                                                                            \
   if (chan == DRTE_PORT)                                                    \
   {                                                                         \
      Duart_CB[4].MCR_Copy |= U_DTR;                                         \
      UART_MCR =  Duart_CB[4].MCR_Copy;                                      \
   }                                                                         \
   else                                                                      \
   {                                                                         \
      *Duart_CB[chan].pOPR |= DTR;                                           \
   }                                                                         \
}                                                                            \

/*==========================================================================*
 * MACRO: Set_DTR_OFF                                                       *
 *                                                                          *
 * PURPOSE: Sets DTR for channel specified to OFF (MARK).                   *
 *                                                                          *
 *==========================================================================*/

#define Set_DTR_OFF(chan)                                                    \
                                                                             \
{                                                                            \
   if (chan == DRTE_PORT)                                                    \
   {                                                                         \
      Duart_CB[4].MCR_Copy &= ~U_DTR;                                        \
      UART_MCR =  Duart_CB[4].MCR_Copy;                                      \
   }                                                                         \
   else                                                                      \
   {                                                                         \
      *Duart_CB[chan].pOPR &= ~DTR;                                          \
   }                                                                         \
}                                                                            \

/*=========================================================================*
 * MACRO: Set_UART_Baud                                                    *
 *                                                                         *
 * PURPOSE: Set the UART Baud Rate.                                        *
 *                                                                         *
 *=========================================================================*/

#define Set_UART_Baud(baud)                                                  \
/* void Set_UART_Baud (INT32 baud) */                                        \
{                                                                            \
   if (baud < 2)                                                             \
   {                                                                         \
      Duart_CB[4].DLM_Copy = 0xFF;                                           \
      Duart_CB[4].DLL_Copy = 0xFF;                                           \
   }                                                                         \
   else if (baud > 115200)                                                   \
   {                                                                         \
      Duart_CB[4].DLM_Copy = 0x00;                                           \
      Duart_CB[4].DLL_Copy = 0x01;                                           \
   }                                                                         \
   else                                                                      \
   {                                                                         \
      Duart_CB[4].DLM_Copy = ((460800 / baud) + 1) >> 9;                     \
      Duart_CB[4].DLL_Copy = (((460800 / baud) + 1) >> 1) & 0xFF;            \
   }                                                                         \
   INTERRUPTS_OFF;                                                           \
   UART_LCR = Duart_CB[4].LCR_Copy | U_DLE;                                  \
   UART_DLL = Duart_CB[4].DLL_Copy;                                          \
   UART_DLM = Duart_CB[4].DLM_Copy;                                          \
   UART_LCR = Duart_CB[4].LCR_Copy;                                          \
   INTERRUPTS_ON;                                                            \
}                                                                            \



/*****************************/
/*   TYPEDEFS                */
/*****************************/

/* define the status word for MR registers */

typedef union
{
   struct
   {
      unsigned  x_transp    : 1;  /* 7 - Xon/Xoff transparency */
      unsigned  ar_transp   : 1;  /* 6 - address recognition transparency */
      unsigned  tx_int      : 2;  /* 4-5 - tx interrupt fill level */
      unsigned  fc_mode     : 2;  /* 2-3 - in-band flow control mode */
      unsigned  ar_ctl      : 4;  /* 0-1 - address recognition control */
   } bits;
   BIT8 byte;
}  MR0_TYPE;


typedef union
{
   struct
   {
      unsigned  rx_ctl_RTS  : 1;  /* 7 - Rx Controls RTS (duart handshake) */
      unsigned  isr_masked  : 1;  /* 6 - interrupt status masking */
      unsigned  error_mode  : 1;  /* 5 - error mode */
      unsigned  parity      : 3;  /* 2-4 - parity */
      unsigned  data_bits   : 2;  /* 0-1 - bits per character */
   } bits;
   BIT8 byte;
}  MR1_TYPE;


typedef union
{
   struct
   {
      unsigned  chan_mode   : 2;  /* 6-7 - modes - normal,test etc */
      unsigned  tx_ctl_RTS  : 1;  /* 5 - tx control of RTS (half duplex) */
      unsigned  CTS_ctl_tx  : 1;  /* 4 - CTS enables tx (HW and Duart handshake) */
      unsigned  rx_int      : 2;  /* 2-3 - rx interrupt fill level */
      unsigned  stop_bits   : 4;  /* 0-3 - stop bit length */
   } bits;
   BIT8 byte;
}  MR2_TYPE;


/* Define data structures for the DUART's control block. */
typedef  struct
{
   MIO_HDR_TYPE  *pRd_Packet;      /* pointer to a read packet */
   MIO_HDR_TYPE  *pWr_Packet;      /* pointer to a write packet */
   U_INT16  Waiting_For_Rd_Packet; /* Indicates no more read packets */
   U_INT16  Transmitting;      /*indicates write packet is being transmitted*/
   U_INT16  Handshake_Timeout; /* test if host holds us off for too long */
   BIT8    *pRd_Data_Start;    /* pointer to start of packet's data buffer */
   BIT8    *pWr_Data_Start;    /* pointer to start of packet's data buffer */
   BIT8    *pWr_Transfer;      /* pointer to next char to be output */
   volatile BIT8    *pMode0;   /* pointer to DUART mode0 register */
   volatile BIT8    *pMode1;   /* pointer to DUART mode1 register */
   volatile BIT8    *pMode2;   /* pointer to DUART mode2 register */
   volatile BIT8    *pIMR;     /* pointer to DUART interrupt mask register */
   volatile BIT8    *pStatus;  /* pointer to DUART status register */
   volatile BIT8    *pRxClock; /* pointer to DUART Rx clock register */
   volatile BIT8    *pTxClock; /* pointer to DUART Tx clock register */
   volatile BIT8    *pCmd;     /* pointer to DUART command register */
   volatile BIT8    *pRx_Tx;   /* ptr to DUART receive and transmit reg */
   volatile BIT8    *pIPR;     /* pointer to DUART input port register */
   volatile BIT8    *pOPR;     /* pointer to DUART output port register */
   MR0_TYPE Mode0_Copy;        /* copy of the last value sent to MR0 */
   MR1_TYPE Mode1_Copy;        /* copy of the last value sent to MR1 */
   MR2_TYPE Mode2_Copy;        /* copy of the last value sent to MR2 */
   BIT8    IMR_Copy;           /* copy of the latest value sent to IMR */
   BIT8    Clock_Copy;         /* copy of the last value sent to Rx CSR and Tx CSR */
   BIT8    Term_Seq;           /* terminating sequence */
   BIT8    Error;              /* saves errors from duart */
   BIT8    Data_Loss;          /* Rx data was lost */
   BIT8    Tx_XonXoff_State;   /* indicates tx data is XOFFed by host */
   BIT8    Rx_XonXoff_State;   /* indicates IQ XOFFed host for rx data */
   BIT8    Rx_Send_XON;        /* indicates XON needs to be transmitted */
   BIT8    Rx_Send_XOFF;       /* indicates XOFF needs to be transmitted */
   BIT8     IER_Copy;          /* copy of the last value sent to IER */
   BIT8     FCR_Copy;          /* copy of the last value sent to FCR */
   BIT8     LCR_Copy;          /* copy of the last value sent to LCR */
   BIT8     MCR_Copy;          /* copy of the last value sent to MCR */
   BIT8     DLL_Copy;          /* copy of the last value sent to DLL */
   BIT8     DLM_Copy;          /* copy of the last value sent to DLM */

}  DUART_CB_TYPE;


/*
 * define data structure containing the variables used by a small buffer
 *    containing the duart receive data.
 *    One buffer for each channel: port A and port B
 */

typedef  struct
{
   U_INT16  *pbuffer;        /* pointer to data buffer */
   U_INT16  *pbufend;        /* pointer to the end of the buffer */
   U_INT16  *pfront;         /* front of queue - remove data from front */
   U_INT16  *prear;          /* rear of queue - add data to rear */
   U_INT16  size;            /* size of queue in words */
   U_INT16  count;           /* number of 16 bit words in queue */
} DUARTBUF_RX_TYPE;

typedef  struct
{
   U_INT8  *pbuffer;        /* pointer to data buffer */
   U_INT8  *pbufend;        /* pointer to the end of the buffer */
   U_INT8  *pfront;         /* front of queue - remove data from front */
   U_INT8  *prear;          /* rear of queue - add data to rear */
   U_INT16  size;           /* size of queue in words */
   U_INT16  count;          /* number of 8 bit words in queue */
} DUARTBUF_TX_TYPE;

typedef enum
{
   NO_RS232_TEST = -1,
   HST_RS232_SELF_TEST = 1,
   HST_RS232_DATA_LOOPBACK = 2,
   HST_RS232_CONTROL_LOOPBACK = 3,
   OBC_RS232_SELF_TEST = 4,
   OBC_RS232_DATA_LOOPBACK = 5,
   OBC_RS232_CONTROL_LOOPBACK = 6,
   INJ_1_RS232_SELF_TEST = 7,
   INJ_1_RS232_DATA_LOOPBACK = 8,
   INJ_1_RS232_CONTROL_LOOPBACK = 9,
   INJ_2_RS232_SELF_TEST = 10,
   INJ_2_RS232_DATA_LOOPBACK = 11,
   INJ_2_RS232_CONTROL_LOOPBACK = 12,
   TRAY_RS232_SELF_TEST = 13,
   TRAY_RS232_DATA_LOOPBACK = 14,
   TRAY_RS232_CONTROL_LOOPBACK = 15
} RS232_TEST_TYPE;

/*****************************/
/*   EXTERNS                 */
/*****************************/

/* working copy of RS232 Configuration */
   extern   BAUD_RATE_TYPE  Serial_Port_Baud_Rate[5]; /* baud rate */
   extern   HANDSHAKE_TYPE  Serial_Port_Handshake[5]; /* Data Flow Control */
   extern   PARITY_TYPE     Serial_Port_Parity[5];    /* parity */
   extern   DATA_BITS_TYPE  Serial_Port_Data_Bits[5]; /* number data bits */
   extern   STOP_BITS_TYPE  Serial_Port_Stop_Bits[5]; /* number stop bits */
   extern   TERM_SEQ_TYPE   Serial_Port_Term_Seq[5];  /* terminating seq  */

extern  RS232_TEST_TYPE   Rs232_Self_Test;

/* create a Control Block for each UART */
extern DUART_CB_TYPE  Duart_CB[5];
extern DUARTBUF_RX_TYPE DuartRxBuf_V[5];   /* create vars for DuartBuf */
extern DUARTBUF_TX_TYPE DuartTxBuf_V[5];   /* create vars for DuartBuf */



/*****************************/
/*   FUNCTION PROTOTYPES     */
/*****************************/

/* put DuartISR in SysCode */
#ifndef mccabe
#pragma SECTION PROG=SysCode
#endif
void DuartISR(void);
#ifndef mccabe
#pragma SECTION UNDO
#endif

void TurnOnDuart(U_INT16  chan, SERIAL_PARMS_TYPE serial_parms);
void DUART_ENABLE_TX_A_INT(void);

/* put _InitializeDuart in boot area */
#ifndef mccabe
#pragma SECTION PROG=boot
#endif
void  InitializeDuart(void);
#ifndef mccabe
#pragma SECTION UNDO
#endif

U_INT16  DuartWaitingRdPacket(U_INT16 chan);
void DuartEnableRxInt(U_INT16  chan);
void DuartDisableRxInt(U_INT16  chan);
void DuartEnableTxInt(U_INT16  chan);
void DuartDisableTxInt(U_INT16  chan);
void DuartEnableSamplerReset(U_INT16 chan);
void DuartDisableSamplerReset(U_INT16 chan);
void DuartEnableLANReset(void);
void DuartDisableLANReset(void);
void SwapSamplerChannels(void);
DIAG_RESULT DuartPowerOnTest(void);
UI_ERR  DuartModemLinesTest(U_INT16  chan);
UI_ERR  Rs232SelfTest(U_INT16  chan);
UI_ERR  Rs232DataLoopbackTest(U_INT16  chan);
UI_ERR  Rs232ControlLoopbackTest(U_INT16  chan);
void InitiateRs232SelfTest(RS232_TEST_TYPE test_type);
void CheckAndExecRs232SelfTest(void);


#endif
